package com.eerl.pdev.ctm_goto;

import com.eerl.pdev.Tuple;
import com.eerl.pdev.util.Notice;
import com.intellij.openapi.actionSystem.AnAction;
import com.intellij.openapi.actionSystem.AnActionEvent;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.editor.*;
import com.intellij.openapi.fileEditor.FileDocumentManager;
import com.intellij.openapi.fileEditor.FileEditorManager;
import com.intellij.openapi.fileEditor.OpenFileDescriptor;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.module.ModuleManager;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.roots.ModuleRootManager;
import com.intellij.openapi.ui.Messages;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.PsiManager;
import org.jetbrains.annotations.NotNull;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class JumpToTargetAction extends AnAction {

    @Override
    public void actionPerformed(@NotNull AnActionEvent event) {
        Project project = event.getProject();
        if (project == null) {
            return;
        }

        Editor currentEditor = FileEditorManager.getInstance(project).getSelectedTextEditor();
        if (currentEditor == null) {
            Messages.showMessageDialog(project, "No editor is open", "Error", Messages.getErrorIcon());
            return;
        }
        VirtualFile currentFile = FileDocumentManager.getInstance().getFile(currentEditor.getDocument());
        assert currentFile != null;
        String currentFileName = currentFile.getName();

        CaretModel caretModel = currentEditor.getCaretModel();
        int lineNumber = caretModel.getLogicalPosition().line;
        Document currentDocument = currentEditor.getDocument();
        // 当前行内容
        String lineContent = currentDocument.getText().split("\n")[lineNumber].trim();

        if (currentFileName.endsWith("_data.erl")) {
            // 当是在data配置文件，快捷行为是在该文件内寻找sheet定义
            String sheetCase = "{" + extractSheetCase(lineContent) + ",";
            searchPosAndJump(project, event, currentFile, sheetCase);
        } else {
            Tuple<String, String> parsedModAndFunName = parseModAndFunName(lineContent);
            String modeName = parsedModAndFunName.key;
            if(modeName.equals("?MODULE")){
                int dotIndex = currentFileName.lastIndexOf('.');
                if(dotIndex != -1)
                    modeName = currentFileName.substring(0, dotIndex);
            }
            String funName = parsedModAndFunName.val;
            if(modeName.equals("null") || funName.equals("null")) return;

            Module[] modules = ModuleManager.getInstance(project).getModules();
            reverse(modules);
            VirtualFile targetFile = findFile(modules, modeName);

            if (targetFile == null) return;

            // 打开目标文件并查找字符串位置
            final VirtualFile finalTargetFile = targetFile;
            searchPosAndJump(project, event, finalTargetFile, funName);
        }

    }

    // 查找对应位置并跳转
    private void searchPosAndJump(Project project, AnActionEvent event, VirtualFile finalTargetFile, String caseStr) {
        ApplicationManager.getApplication().runReadAction(() -> {
            PsiManager psiManager = PsiManager.getInstance(project);
            com.intellij.psi.PsiFile psiFile = psiManager.findFile(finalTargetFile);
            if (psiFile != null) {
                Document targetDocument = psiFile.getViewProvider().getDocument();
                if (targetDocument != null) {
                    int offset = targetDocument.getText().indexOf(caseStr);
                    if (offset != -1) {
                        int line = targetDocument.getLineNumber(offset);
                        int column = offset - targetDocument.getLineStartOffset(line);
                        LogicalPosition logicalPosition = new LogicalPosition(line, column);
                        openFileAndMoveCaret(project, finalTargetFile, logicalPosition);
                    } else {
                        Notice.popMessage(event, "Matching string not found in the target file");
                    }
                }
            }
        });
    }

    private void openFileAndMoveCaret(Project project, VirtualFile file, LogicalPosition position) {
        OpenFileDescriptor descriptor = new OpenFileDescriptor(project, file);
        Editor editor = FileEditorManager.getInstance(project).openTextEditor(descriptor, true);
        if (editor != null) {
            editor.getCaretModel().moveToLogicalPosition(position);
            editor.getScrollingModel().scrollToCaret(ScrollType.CENTER);
            editor.getSelectionModel().selectLineAtCaret();
        }
    }

    private Tuple<String, String> parseModAndFunName(String line) {
        String patternStr1 = " ?([a-z][a-z0-9_]+):([a-z][a-z0-9_]+)\\(.*\\)";
        Pattern compile1 = Pattern.compile(patternStr1);
        Matcher matcher1 = compile1.matcher(line);
        String modeName;
        String funName;
        if (matcher1.find()) {
            modeName = matcher1.group(1);
            if(modeName.endsWith("_data")){
                funName = matcher1.group(2);
                return new Tuple<>(modeName, funName);
            }
        }
        // 第二个正则表达式模式字符串
        String patternStr2 = "\\{(.*)\\}";
        Pattern compile2 = Pattern.compile(patternStr2);
        Matcher matcher2 = compile2.matcher(line);
        // 检查是否匹配第二个正则表达式
        if (matcher2.find()) {
            String termStr = matcher2.group(1);

            String[] terms = mfaSplit(termStr);
            int length = terms.length;
            if (length < 2) {
                return new Tuple<>("null", "null");
            }else if (length == 2) {
                if(Arrays.stream(terms).allMatch(this::isErlangValidName)){
                    return new Tuple<>(terms[0], terms[1] + "(");
                }
            }else {
                String[] last3Terms = Arrays.copyOfRange(terms, length - 3, length);
                if(isErlangValidName(last3Terms[2])){
                    return new Tuple<>(last3Terms[1], last3Terms[2] + "(");
                }else {
                    return new Tuple<>(last3Terms[0], last3Terms[1] + "(");
                }
            }
        }
        return new Tuple<>("null", "null");
    }
    private boolean isErlangValidName(String name) {
        String regex = "^[a-z][a-z0-9_]*$";
        return name.matches(regex);
    }

    private static String[] mfaSplit(String input) {
        List<String> result = new ArrayList<>();
        // 用于匹配方括号内的内容
        Pattern pattern = Pattern.compile("\\[.*\\]");
        Matcher matcher = pattern.matcher(input);
        int lastEnd = 0;
        while (matcher.find()) {
            // 分割方括号外的内容
            String[] parts = input.substring(lastEnd, matcher.start()).split(",");
            for (String part : parts) {
                if (!part.isEmpty()) {
                    result.add(part.trim());
                }
            }
            // 添加方括号内的整体内容
            result.add(matcher.group());
            lastEnd = matcher.end();
        }
        // 处理最后一个方括号外的内容
        String[] parts = input.substring(lastEnd).split(",");
        for (String part : parts) {
            if (!part.isEmpty()) {
                result.add(part.trim());
            }
        }
        return result.stream().filter(s -> !s.isEmpty()).map(String::trim).toList().toArray(new String[0]);
    }

    private VirtualFile findFile(Module[] modules, String needFindFileName) {
        for (Module module : modules) {
            for (VirtualFile contentRoot : ModuleRootManager.getInstance(module).getContentRoots()) {
                if (contentRoot.isDirectory()) {
                    VirtualFile targetFile = findFile(contentRoot, needFindFileName);
                    if (targetFile != null) {
                        return targetFile;
                    }
                } else if (contentRoot.getNameWithoutExtension().equals(needFindFileName)){
                    return contentRoot;
                }
            }
        }
        return null;
    }

    private VirtualFile findFile(VirtualFile dir, String needFindFileName) {
        for (VirtualFile child : dir.getChildren()) {
            if (child.isDirectory()) {
                VirtualFile targetFile = findFile(child, needFindFileName);
                if (targetFile != null) {
                    return targetFile;
                }
            } else if (child.getNameWithoutExtension().equals(needFindFileName)){
                return child;
            }
        }
        return null;
    }

    private void reverse(Module[] modules) {
        int startPos = 0, endPos = modules.length - 1;
        Module tmp;
        while (startPos < endPos) {
            tmp = modules[startPos];
            modules[startPos] = modules[endPos];
            modules[endPos] = tmp;
            startPos++;
            endPos--;
        }
    }

    private static final Pattern SHEET_NAME_CASE_PATTERN = Pattern.compile(".*(\\[\".*\"]).*");

    // 提取页匹配值
    private String extractSheetCase(String line) {
        Matcher matcher = SHEET_NAME_CASE_PATTERN.matcher(line);
        if (matcher.find()) {
            return matcher.group(1);
        }
        return "null";
    }
}

